home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / kernel / fork.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-09  |  6.6 KB  |  264 lines

  1. /*
  2.  *  linux/kernel/fork.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /*
  8.  * 680x0 support by Hamish Macdonald
  9.  */
  10.  
  11. /*
  12.  *  'fork.c' contains the help-routines for the 'fork' system call
  13.  * (see also system_call.s).
  14.  * Fork is rather simple, once you get the hang of it, but the memory
  15.  * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
  16.  */
  17.  
  18. #include <linux/errno.h>
  19. #include <linux/sched.h>
  20. #include <linux/kernel.h>
  21. #include <linux/mm.h>
  22. #include <linux/stddef.h>
  23. #include <linux/unistd.h>
  24. #include <linux/segment.h>
  25. #include <linux/ptrace.h>
  26. #include <linux/malloc.h>
  27. #include <linux/string.h>
  28.  
  29. #include <asm/segment.h>
  30. #include <asm/system.h>
  31.  
  32. #if defined(__i386__)
  33. asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
  34. #elif defined(__mc68000__)
  35. asmlinkage void ret_from_exception(void);
  36. #endif
  37.  
  38. /* These should maybe be in <linux/tasks.h> */
  39.  
  40. #define MAX_TASKS_PER_USER (NR_TASKS/2)
  41. #define MIN_TASKS_LEFT_FOR_ROOT 4
  42.  
  43. extern int shm_fork(struct task_struct *, struct task_struct *);
  44. long last_pid=0;
  45.  
  46. static int find_empty_process(void)
  47. {
  48.     int free_task;
  49.     int i, tasks_free;
  50.     int this_user_tasks;
  51.  
  52. repeat:
  53.     if ((++last_pid) & 0xffff8000)
  54.         last_pid=1;
  55.     this_user_tasks = 0;
  56.     tasks_free = 0;
  57.     free_task = -EAGAIN;
  58.     i = NR_TASKS;
  59.     while (--i > 0) {
  60.         if (!task[i]) {
  61.             free_task = i;
  62.             tasks_free++;
  63.             continue;
  64.         }
  65.         if (task[i]->uid == current->uid)
  66.             this_user_tasks++;
  67.         if (task[i]->pid == last_pid || task[i]->pgrp == last_pid)
  68.             goto repeat;
  69.     }
  70.     if (tasks_free <= MIN_TASKS_LEFT_FOR_ROOT ||
  71.         this_user_tasks > MAX_TASKS_PER_USER)
  72.         if (current->uid)
  73.             return -EAGAIN;
  74.     return free_task;
  75. }
  76.  
  77. static struct file * copy_fd(struct file * old_file)
  78. {
  79.     struct file * new_file = get_empty_filp();
  80.     int error;
  81.  
  82.     if (new_file) {
  83.         memcpy(new_file,old_file,sizeof(struct file));
  84.         new_file->f_count = 1;
  85.         if (new_file->f_inode)
  86.             new_file->f_inode->i_count++;
  87.         if (new_file->f_op && new_file->f_op->open) {
  88.             error = new_file->f_op->open(new_file->f_inode,new_file);
  89.             if (error) {
  90.                 iput(new_file->f_inode);
  91.                 new_file->f_count = 0;
  92.                 new_file = NULL;
  93.             }
  94.         }
  95.     }
  96.     return new_file;
  97. }
  98.  
  99. int dup_mmap(struct task_struct * tsk)
  100. {
  101.     struct vm_area_struct * mpnt, **p, *tmp;
  102.  
  103.     tsk->mmap = NULL;
  104.     tsk->stk_vma = NULL;
  105.     p = &tsk->mmap;
  106.     for (mpnt = current->mmap ; mpnt ; mpnt = mpnt->vm_next) {
  107.         tmp = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
  108.         if (!tmp)
  109.             return -ENOMEM;
  110.         *tmp = *mpnt;
  111.         tmp->vm_task = tsk;
  112.         tmp->vm_next = NULL;
  113.         if (tmp->vm_inode)
  114.             tmp->vm_inode->i_count++;
  115.         *p = tmp;
  116.         p = &tmp->vm_next;
  117.         if (current->stk_vma == mpnt)
  118.             tsk->stk_vma = tmp;
  119.     }
  120.     return 0;
  121. }
  122.  
  123. #if defined(__i386__)
  124. #define IS_CLONE (regs.orig_eax == __NR_clone)
  125. #elif defined(__mc68000__)
  126. #define IS_CLONE (regs.orig_d0 == __NR_clone)
  127. #endif
  128. #define copy_vm(p) ((clone_flags & COPYVM)?copy_page_tables(p):clone_page_tables(p))
  129.  
  130. /*
  131.  *  Ok, this is the main fork-routine. It copies the system process
  132.  * information (task[nr]) and sets up the necessary registers. It
  133.  * also copies the data segment in its entirety.
  134.  */
  135. asmlinkage int sys_fork(struct pt_regs regs)
  136. {
  137.     struct pt_regs * childregs;
  138.     struct task_struct *p;
  139.     int i,nr;
  140.     struct file *f;
  141.     unsigned long clone_flags = COPYVM | SIGCHLD;
  142.  
  143.     if(!(p = (struct task_struct*)__get_free_page(GFP_KERNEL)))
  144.         goto bad_fork;
  145.     nr = find_empty_process();
  146.     if (nr < 0)
  147.         goto bad_fork_free;
  148.     task[nr] = p;
  149.     *p = *current;
  150.     p->kernel_stack_page = 0;
  151.     p->state = TASK_UNINTERRUPTIBLE;
  152.     p->flags &= ~(PF_PTRACED|PF_TRACESYS);
  153.     p->pid = last_pid;
  154.     p->swappable = 1;
  155.     p->p_pptr = p->p_opptr = current;
  156.     p->p_cptr = NULL;
  157.     SET_LINKS(p);
  158.     p->signal = 0;
  159.     p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
  160.     p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
  161.     p->leader = 0;        /* process leadership doesn't inherit */
  162.     p->utime = p->stime = 0;
  163.     p->cutime = p->cstime = 0;
  164.     p->min_flt = p->maj_flt = 0;
  165.     p->cmin_flt = p->cmaj_flt = 0;
  166.     p->start_time = jiffies;
  167. /*
  168.  * set up new TSS and kernel stack
  169.  */
  170.     if (!(p->kernel_stack_page = __get_free_page(GFP_KERNEL)))
  171.         goto bad_fork_cleanup;
  172. #if defined(__i386__)
  173.     p->tss.es = KERNEL_DS;
  174.     p->tss.cs = KERNEL_CS;
  175.     p->tss.ss = KERNEL_DS;
  176.     p->tss.ds = KERNEL_DS;
  177.     p->tss.fs = USER_DS;
  178.     p->tss.gs = KERNEL_DS;
  179.     p->tss.ss0 = KERNEL_DS;
  180.     p->tss.esp0 = p->kernel_stack_page + PAGE_SIZE;
  181.     p->tss.tr = _TSS(nr);
  182.     childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
  183.     p->tss.esp = (unsigned long) childregs;
  184.     p->tss.eip = (unsigned long) ret_from_sys_call;
  185.     *childregs = regs;
  186.     childregs->eax = 0;
  187.     p->tss.back_link = 0;
  188.     p->tss.eflags = regs.eflags & 0xffffcfff;    /* iopl is always 0 for a new process */
  189.     if (IS_CLONE) {
  190.         if (regs.ebx)
  191.             childregs->esp = regs.ebx;
  192.         clone_flags = regs.ecx;
  193.         if (childregs->esp == regs.esp)
  194.             clone_flags |= COPYVM;
  195.     }
  196.     p->exit_signal = clone_flags & CSIGNAL;
  197.     p->tss.ldt = _LDT(nr);
  198.     if (p->ldt) {
  199.         if ((p->ldt = (struct desc_struct*) __get_free_page(GFP_KERNEL)) != NULL)
  200.             memcpy(p->ldt, current->ldt, PAGE_SIZE);
  201.     }
  202.     p->tss.bitmap = offsetof(struct tss_struct,io_bitmap);
  203.     for (i = 0; i < IO_BITMAP_SIZE+1 ; i++) /* IO bitmap is actually SIZE+1 */
  204.         p->tss.io_bitmap[i] = ~0;
  205.     if (last_task_used_math == current)
  206.         __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387));
  207. #elif defined(__mc68000__)
  208.     p->tss.sr = 0x3000;
  209.     p->tss.fs = 1;
  210.     p->tss.fpstate[0] = 0;
  211.     childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
  212.     *childregs = regs;
  213.     childregs->d0 = 0;
  214.     p->tss.regs[11] = (unsigned long)childregs - 4;
  215.     *(void (**)(void))p->tss.regs[11] = ret_from_exception;
  216.     if (IS_CLONE) {
  217.         if (regs.d1)
  218.             childregs->usp = regs.d1;
  219.         clone_flags = regs.d2;
  220.         if (childregs->usp == regs.usp)
  221.             clone_flags |= COPYVM;
  222.     }
  223.     p->exit_signal = clone_flags & CSIGNAL;
  224. #endif
  225.     p->semun = NULL; p->shm = NULL;
  226.     if (copy_vm(p) || shm_fork(current, p))
  227.         goto bad_fork_cleanup;
  228.     if (clone_flags & COPYFD) {
  229.         for (i=0; i<NR_OPEN;i++)
  230.             if ((f = p->filp[i]) != NULL)
  231.                 p->filp[i] = copy_fd(f);
  232.     } else {
  233.         for (i=0; i<NR_OPEN;i++)
  234.             if ((f = p->filp[i]) != NULL)
  235.                 f->f_count++;
  236.     }
  237.     if (current->pwd)
  238.         current->pwd->i_count++;
  239.     if (current->root)
  240.         current->root->i_count++;
  241.     if (current->executable)
  242.         current->executable->i_count++;
  243.     dup_mmap(p);
  244. #ifdef __i386__
  245.     set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
  246.     if (p->ldt)
  247.         set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,p->ldt, 512);
  248.     else
  249.         set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&default_ldt, 1);
  250. #endif
  251.  
  252.     p->counter = current->counter >> 1;
  253.     p->state = TASK_RUNNING;    /* do this last, just in case */
  254.     return p->pid;
  255. bad_fork_cleanup:
  256.     task[nr] = NULL;
  257.     REMOVE_LINKS(p);
  258.     free_page(p->kernel_stack_page);
  259. bad_fork_free:
  260.     free_page((long) p);
  261. bad_fork:
  262.     return -EAGAIN;
  263. }
  264.